﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Input;
using VMDS.GUIClient.Helper;
using VMDS.GUIClient.Model;
using VMDS.Settings;

namespace VMDS.GUIClient.ViewModels
{
    using System.Management;

    using VMDS.Business.Processes;

    enum MemoryAllocationOption
    {
        Minimum,Meduim,Maximum,Custom
    }
    class StartDialogViewModel:BaseViewModel
    {
        private bool nclose;
        public bool IsNeedToClose
        {
            get
            {
                return nclose;
            }
            set
            {
                nclose = value;
                this.OnPropertyChanged(()=>IsNeedToClose);
            }
        }
        public ICommand NeedClose
        {
            get
            {
                return new BaseCommand(()=>IsNeedToClose=!IsNeedToClose);
            }
        }
        private bool _visible;
        public bool Visible
        {
            get { return _visible; }
            set 
            { 
                _visible = value;
                init();
                OnPropertyChanged(() => Visible);
                OnPropertyChanged(() => DoMaximum); 
                OnPropertyChanged(() => DoMedium);
                OnPropertyChanged(() => DoMinimum);
            }
        }

        private MemoryAllocationOption CurrentMemory;

        private bool _exp;
        public bool Expanded
        {
            get { return _exp; }
            set { _exp = value;OnPropertyChanged(()=>Expanded); }
        }

        private bool _imax;
        public bool IsMaximum
        {
            get { return _imax; }
            set { _imax = value; if (value) CurrentMemory = MemoryAllocationOption.Maximum;
                OnPropertyChanged(() => IsMaximum); }
        }

        private bool _imed;
        public bool IsMedium
        {
            get { return _imed; }
            set
            {
                _imed = value; if (value) CurrentMemory = MemoryAllocationOption.Meduim;
                OnPropertyChanged(()=>IsMedium); }
        }
        private bool _imin;
        public bool IsMinimum
        {
            get { return _imin; }
            set
            {
                _imin = value; if (value) CurrentMemory = MemoryAllocationOption.Minimum;
                OnPropertyChanged(()=>IsMinimum); }
        }

        void SetAllocation(bool min,bool med, bool max,bool cust)
        {
            IsMedium = med;
            IsMinimum = min;
            IsMaximum = max;
            IsCustom = cust;
        }


        public ICommand DoCustom
        {
            get { return new BaseCommand(() => SetAllocation(false, false, false, true)); }
        }

        public ICommand DoMinimum
        {
            get { return new BaseCommand(() => SetAllocation(true, false, false,false)); }
        }
        public ICommand DoMedium
        {
            get { return new BaseCommand(() => SetAllocation(false, true, false,false),CanMedium); }
        }
        public ICommand DoMaximum
        {
            get { return new BaseCommand(() => SetAllocation(false, false, true,false), CanMax); }
        }
        public ICommand Start
        {
            get { return new BaseCommand(startvm); }
        }
        public ICommand Close { get { return new BaseCommand(() => Visible = false); } }
        
        private string _name;
        public string VmName
        {
            get { return _name; }
            set { _name = value;OnPropertyChanged(()=>VmName); }
        }
            

        int GetCores()
        {
            return new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get().Cast<ManagementBaseObject>().Sum(item => int.Parse(item["NumberOfCores"].ToString()));
        }

        bool CanMax()
        {
            return FreeRam() > 767;
        }

        bool CanMedium()
        {
            return FreeRam() > 256;
        }

        int FreeRam()
        {
            var performanceCounter1 = new System.Diagnostics.PerformanceCounter();
            performanceCounter1.CategoryName = "Memory";
            performanceCounter1.CounterName = "Available Bytes";
            var result=(int)((performanceCounter1.NextValue()/1024)/1024);
            return result;
        }

        void ProcessVmxFile(string vmx)
        {
            List<string> lines = new List<string>(File.ReadAllLines(vmx));
            List<string> newlines = new List<string>();
            var keep = false;
            foreach (var line in lines)
            {
                var newline = line;
                if (line.Contains("memsize"))
                {
                    string size="";
                    var ram = FreeRam();

                    if (IsNeedToClose)
                    {
                        Process currentProcess =Process.GetCurrentProcess();
                        var mb = (int)currentProcess.PrivateMemorySize64/1024/1024;
                        ram = ram + mb;
                    }
                    if (CurrentMemory == MemoryAllocationOption.Meduim)
                    {
                        if (ram > 512) size = "512";
                        if (ram < 512) size = (ram - ram % 4).ToString();
                    }
                    if (CurrentMemory == MemoryAllocationOption.Maximum)
                    {
                        size = (ram - ram % 4).ToString();
                        if (ram > 1023) size = "1024";
                    }
                    if (CurrentMemory == MemoryAllocationOption.Minimum)
                    {
                        size = "256";
                        
                    }
                    if (CurrentMemory == MemoryAllocationOption.Custom)
                    {
                        size = CustomRAM.ToString();

                    }
                    newline = "memsize = \""+size+"\"";
                }
                

                if (line.Contains("sharedFolder0.enabled"))
                {
                    newline = "sharedFolder0.enabled = \"TRUE\"";
                }
                if (line.Contains("numvcpus"))
                {
                    newline = "numvcpus = \"" + GetCores() + "\"";
                }

                if (line.Contains("uuid.action"))
                {
                    newline = "uuid.action = \"create\"";
                    keep = true;
                }
                newlines.Add(newline);
            }
            if (!keep)
            {
                newlines.Add("uuid.action = \"keep\"");
            }
            File.WriteAllLines(vmx, newlines);
        }


        void startvm()
        {
            var local = new ClientConfiguration(@"d:\virtual\data\config.ini").LocalStorage + "vm\\" + VmName;
            var vmx = Directory.EnumerateFiles(local, "*.vmx").FirstOrDefault(x => new FileInfo(x).Extension == ".vmx");
            if (vmx != null)
            {
                ProcessVmxFile(vmx);
                var vmw = new SoftWare() { Productname = "VMware Workstation" };
                vmw.Update();
                string path = Repozitory.VMplayerPath + "\\vmplayer.exe";
              
                if (vmw.Installed) path = vmw.InstallPath + "\\vmware.exe";

                Process.Start(path, "\"" + vmx + "\"");
            }
            if (IsNeedToClose) Environment.Exit(0);
            Visible = false;
            
        }

        private int _cram;
        public int CustomRAM
        {
            get { return _cram; }
            set { _cram = value;OnPropertyChanged(()=>CustomRAM); }
        }

        private int _mram;
        public int MaxRAM
        {
            get { return _mram; }
            set { _mram = value;OnPropertyChanged(()=>MaxRAM); }
        }

        private bool _custom;
        public bool IsCustom
        {
            get { return _custom; }
            set { _custom = value; if (value)
            {
                setmax();
                CurrentMemory = MemoryAllocationOption.Custom;
            }
                OnPropertyChanged(() => IsCustom); }
        }


        private static StartDialogViewModel _inst;
        public static StartDialogViewModel Instance
        {
            get { return _inst ?? (_inst = new StartDialogViewModel()); }
        }

        void setmax()
        {
            var ram = FreeRam();
            MaxRAM = ram - ram % 4;
        
        }

        void init()
        {
            setmax();
            IsNeedToClose = true;
            Expanded = false;
            IsMaximum = false;
            IsMedium = false;
            IsMinimum = false;
            IsCustom = false;
            CustomRAM = 64;           
            if (CanMedium()) IsMedium = true;
            else IsMinimum = true;
        }

        public StartDialogViewModel()
        {
           init();

            //Visible = true;
        }

    }
}
